package com.zhuhjay.chat.client.proxy;

import com.zhuhjay.chat.client.manager.RpcServicePromiseManager;
import com.zhuhjay.chat.message.RpcRequestMessage;
import com.zhuhjay.chat.util.GenericSequenceId;
import io.netty.channel.Channel;
import io.netty.util.concurrent.DefaultPromise;

import java.lang.reflect.Proxy;

/**
 * 封装远程调用的代码，让远调变得简单！
 * @author ZhuHJay
 * @date 2023/3/10 23:42
 */
public class RpcServiceProxy {

    @SuppressWarnings("all")
    public static <T> T getServiceProxy(Class<T> clazz, Channel channel) {
        ClassLoader classLoader = clazz.getClassLoader();
        Class<?>[] interfaces = new Class[]{clazz};
        return (T) Proxy.newProxyInstance(classLoader, interfaces, (proxy, method, args) -> {
            int sequenceId = GenericSequenceId.nextId();
            RpcRequestMessage req = new RpcRequestMessage(
                    sequenceId,
                    clazz.getName(),
                    method.getName(),
                    method.getReturnType(),
                    method.getParameterTypes(),
                    args
            );
            channel.writeAndFlush(req);

            DefaultPromise<Object> promise = new DefaultPromise<>(channel.eventLoop());
            RpcServicePromiseManager.push(sequenceId, promise);

            // 等待远程调用
            promise.await();
            if (promise.isSuccess()) {
                return promise.getNow();
            } else {
                throw new RuntimeException(promise.cause());
            }
        });
    }


}
